`ifndef SWITCH_ENV_SV
`define SWITCH_ENV_SV

`include "mac_agent.sv"
`include "switch_virtual_sequencer.sv"
`include "switch_scb.sv"
`include "switch_refm.sv"
`include "coverage_pkg.sv"

class switch_env extends uvm_env;

	`uvm_component_utils(switch_env)

	mac_agent i_agent[PORT_NUM];
	mac_agent o_agent[PORT_NUM];
	switch_refm		m_refm;
	switch_scb		m_scb;
	coverage_switch 	cov;
	switch_virtual_sequencer virt_sqr;

	uvm_tlm_analysis_fifo #(mac_seq_item) imon2model_fifo[PORT_NUM];
	uvm_tlm_analysis_fifo #(mac_seq_item) model2scb_fifo[PORT_NUM];
	uvm_tlm_analysis_fifo #(mac_seq_item) omon2scb_fifo[PORT_NUM];

	extern function new(string name, uvm_component parent);
	extern function void build_phase(uvm_phase phase);
	extern function void connect_phase(uvm_phase phase);

endclass: switch_env

function switch_env::new(string name, uvm_component parent);
	super.new(name, parent);
	`uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
endfunction: new

function void switch_env::build_phase(uvm_phase phase);
	super.build_phase(phase);
	`uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);

	m_scb = switch_scb::type_id::create("m_scb", this);
	m_refm = switch_refm::type_id::create("m_refm", this);
	virt_sqr = switch_virtual_sequencer::type_id::create("virt_sqr", this);
	for (int i = 0; i < PORT_NUM; i++) begin
		i_agent[i] = mac_agent::type_id::create($sformatf("i_agent_%0d", i), this);
		o_agent[i] = mac_agent::type_id::create($sformatf("o_agent_%0d", i), this);
		uvm_config_db# (uvm_active_passive_enum)::set(this, $sformatf("i_agent_%0d", i), "is_active", UVM_ACTIVE);
		uvm_config_db# (uvm_active_passive_enum)::set(this, $sformatf("o_agent_%0d", i), "is_active", UVM_PASSIVE);
		uvm_config_db# (int)::set(this, $sformatf("i_agent_%0d.*", i), "port_num", i);
		uvm_config_db# (int)::set(this, $sformatf("o_agent_%0d.*", i), "port_num", i);
		imon2model_fifo[i] = new($sformatf("imon2model_fifo%0d", i), this);
		model2scb_fifo[i] = new($sformatf("model2scb_fifo%0d", i), this);
		omon2scb_fifo[i] = new($sformatf("omon2scb_fifo_%0d", i), this);
	end
`ifdef COV_EN
		cov = coverage_switch::type_id::create("cov", this);
`endif

endfunction: build_phase


function void switch_env::connect_phase(uvm_phase phase);
	`uvm_info(get_type_name(), "In connect phase", UVM_HIGH)
	for (int i = 0; i < PORT_NUM; i++) begin
		i_agent[i].m_monitor.analysis_port.connect(imon2model_fifo[i].analysis_export);
		m_refm.i_refm_port[i].connect(imon2model_fifo[i].blocking_get_export);
		m_refm.o_refm_ap[i].connect(model2scb_fifo[i].analysis_export);
		m_scb.exp_port[i].connect(model2scb_fifo[i].blocking_get_export);
		o_agent[i].m_monitor.analysis_port.connect(omon2scb_fifo[i].analysis_export);
		m_scb.act_port[i].connect(omon2scb_fifo[i].blocking_get_export);
		virt_sqr.mac_mii_sqrs[i] = i_agent[i].ms_sequencer;
	end

endfunction

`endif
